/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.rpgmapper.gui.menu;

import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.math.FastMath;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.ui.Picture;
import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import org.rpgmapper.JmeMain;
import org.rpgmapper.tools.AppContext;

/**
 *
 * @author Nehon
 */
public class MenuItem implements ActionListener {

    protected Node mainNode;
    protected Picture picture;
    protected Node childrenNode;
    private static final float ROTATION = FastMath.PI / 4;
    private static final float HALF_SIZE = 32f;
    private static final float SIZE = HALF_SIZE * 2f;
    private static float DISTANCE = -125f;
    protected int nbChilden = 0;
    protected SafeArrayList<MenuItem> children;
    protected boolean visible = false;
    protected boolean requestHide = false;
    private MenuItemListener listener;

    public MenuItem(String name, String picPath) {
        mainNode = new Node(name);        
        if (picPath != null) {
            this.picture = new Picture(name + "-picture");
            picture.setImage(AppContext.getAssetManager(), picPath, true);
            picture.setHeight(SIZE);
            picture.setWidth(SIZE);
            mainNode.attachChild(picture);            
            picture.addControl(new PictureControl());
            AppContext.getInputManager().addListener(this, "click");
            AppContext.getInputManager().addMapping("click", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        }

    }

    public void addItem(MenuItem item) {
        if (childrenNode == null) {
            childrenNode = new Node(mainNode.getName() + "-children");
            children = new SafeArrayList(MenuItem.class);
            if (picture != null) {
                childrenNode.setLocalTranslation(picture.getLocalTranslation());
            }
            mainNode.attachChild(childrenNode);
            childrenNode.setCullHint(Spatial.CullHint.Always);            
        }
        childrenNode.attachChild(item.mainNode);
        children.add(item);

        if (item.picture != null) {
            item.picture.setLocalTranslation(0, DISTANCE, 0);
            if (item.childrenNode != null) {
                item.childrenNode.setLocalTranslation(0, DISTANCE, 0);
            }
        }
        TempVars vars = TempVars.get();
        vars.quat1.fromAngleAxis(ROTATION * (float) nbChilden, Vector3f.UNIT_Z);
        item.mainNode.setLocalRotation(vars.quat1);
        vars.quat1.fromAngleAxis(-ROTATION * (float) nbChilden / 2, Vector3f.UNIT_Z);
        childrenNode.setLocalRotation(vars.quat1);
        vars.release();
        nbChilden++;
    }

    public Node getMainNode() {
        return mainNode;
    }

    public void expand(boolean visible) {
        if (visible) {
            childrenNode.setCullHint(Spatial.CullHint.Never);
            for (MenuItem menuItem : children) {
                menuItem.visible = visible;
            }
        } else {           
            for (MenuItem menuItem : children) {
                menuItem.requestHide = true;
                menuItem.picture.getControl(PictureControl.class).time = 0;
            }

        }


    }

    public boolean isExpanded() {
        if (childrenNode == null) {
            return false;
        }
        return childrenNode.getCullHint() == Spatial.CullHint.Never;
    }

    public void onAction(String name, boolean isPressed, float tpf) {

        if (name.equals("click") && isPressed) {

            Vector2f pos = AppContext.getInputManager().getCursorPosition();
            Vector3f picPos = picture.getWorldTranslation();
            if ((pos.x >= picPos.x && pos.x <= picPos.x + SIZE) && (pos.y >= picPos.y && pos.y <= picPos.y + SIZE)) {
                if (childrenNode != null) {
                    expand(!isExpanded());
                }
                if(listener!=null){
                    listener.onClick();
                }
                
            }
        }
    }

    private class PictureControl extends AbstractControl {

        private boolean added = false;
        protected float time = 0;
        Vector2f v = new Vector2f();

        @Override
        protected void controlUpdate(float tpf) {
            if (visible) {
                TempVars vars = TempVars.get();
                if (!added) {
                    vars.quat1.set(mainNode.getWorldRotation()).inverseLocal().normalizeLocal();
                    vars.vect1.set(-HALF_SIZE, 0, 0);
                    picture.setLocalRotation(vars.quat1);
                    picture.move(vars.quat1.mult(vars.vect1, vars.vect1));
                    v.set(picture.getLocalTranslation().x, picture.getLocalTranslation().y);
                    added = true;
                }


                time += tpf * 3;
                if (!requestHide) {
                    if (time <= 0.5f) {
                        mainNode.setLocalScale(time * 2);
                    } else {
                        mainNode.setLocalScale(1);
                    }
                } else {
                    if (time <= 0.5f) {
                        mainNode.setLocalScale(1.0f - time * 2);
                    } else {
                        mainNode.setLocalScale(0);
                        visible = false;
                        mainNode.getParent().setCullHint(Spatial.CullHint.Always);
                        requestHide = false;
                    }

                }
                vars.vect2d.set(v);
                vars.vect2d.x += FastMath.sin(time) / 2 + FastMath.cos(time) / 2;
                vars.vect2d.y += FastMath.sin(time) / 2;
                picture.setLocalTranslation(vars.vect2d.x, vars.vect2d.y, 0);

                vars.release();

            } else {
                time = 0;
            }

        }

        @Override
        protected void controlRender(RenderManager rm, ViewPort vp) {
        }

        public Control cloneForSpatial(Spatial spatial) {
            return null;
        }
    }
    
    public void setListener(MenuItemListener l){
        listener = l;
    }
        
}
